#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <math.h>
#include <ctype.h>
#include <unistd.h>
#include "shm_reader.h"
#include "sensor_thread.h"
#include "mqtt_handler.h"

extern int running;
extern MQTTClient mqttClient;
extern int current_mode; // 1=定时上报 2=对比上报 3=查询上报
extern cJSON* baseline_data; // 用于对比上报的基准数据
extern pthread_mutex_t data_mutex; // 保护基准数据
extern pthread_mutex_t mode_mutex;
extern pthread_mutex_t mqtt_mutex;
extern char* shm_ptr;
extern int shm_id;


// 上报变化的数据点
void report_changed_data(cJSON* current) {
    //如果没有基准数据或者数据有变化
    if (!baseline_data || !cJSON_Compare(current, baseline_data, 1)) {
        char* current_str = cJSON_PrintUnformatted(current);//cJSON转换为字符串
        printf("Reporting changed data: %s\n", current_str);
        safe_mqtt_publish(mqttClient, "sensor/data", current_str);
        free(current_str);//及时释放
    }
  
    // 更新基准数据，先释放旧数据，再复制新数据
    cJSON_Delete(baseline_data);
    baseline_data = cJSON_Duplicate(current, 1);

}
    

// 传感器数据读取线程
void* sensor_thread(void* arg) {
    if (init_shm() != 0) {
        return NULL;
    }
    
    while (running) {
        char* sensor_data = read_shm_data();
        
        if (sensor_data && strlen(sensor_data) > 0) {

             // 加锁读取 current_mode
            pthread_mutex_lock(&mode_mutex);
            int mode = current_mode;
            pthread_mutex_unlock(&mode_mutex);

            switch (mode) {
                case 1: // 定时上报模式
                    printf("Sending sensor data (periodic): %s\n", sensor_data);
                    safe_mqtt_publish(mqttClient, "sensor/data", sensor_data);
                    break;
                    
                case 2: // 对比上报模式
                    pthread_mutex_lock(&data_mutex);
                    cJSON* current = cJSON_Parse(sensor_data);
                    
                    if (!baseline_data) {
                        // 初始基准数据
                        baseline_data = cJSON_Duplicate(current, 1);
                        printf("Setting baseline data\n");
                    } else {
                        // 比较并上报变化
                        report_changed_data(current);
                    }
                    
                    cJSON_Delete(current);
                    pthread_mutex_unlock(&data_mutex);
                    break;
                    
                case 3: // 刷新上报模式 - 不主动上报
                    // 数据将只在收到刷新命令时上报
                    break;
            }
        }
        free(sensor_data);
        sleep(2); // 2s读取间隔
    }
    cleanup_shm();
    return NULL;
}


// 自定义字符串比较函数
static int string_compare(const char *str1, const char *str2, int case_sensitive) {
    if (str1 == str2) return 0; // 相同指针
    if (str1 == NULL || str2 == NULL) return -1; // 任一为空
    
    if (case_sensitive) {
        return strcmp(str1, str2);
    } else {
        // 不区分大小写比较
        while (*str1 && *str2) {
            if (tolower((unsigned char)*str1) != tolower((unsigned char)*str2)) {
                return *str1 - *str2;
            }
            str1++;
            str2++;
        }
        return *str1 - *str2;
    }
}

// 浮点数比较，处理浮点精度问题
static int double_compare(double a, double b) {
    // 处理NaN和无穷大
    if (isnan(a) && isnan(b)) return 0;
    if (isinf(a) && isinf(b)) return (a > 0) == (b > 0) ? 0 : 1;
    
    // 处理接近零的情况
    if (fabs(a - b) < 1e-9) return 0;
    
    // 处理较大数值
    double max = fmax(fabs(a), fabs(b));
    if (max < 1e10) {
        return fabs(a - b) < 1e-9 ? 0 : 1;
    }
    
    // 相对误差比较
    return fabs(a - b) <= max * 1e-9 ? 0 : 1;
}

// 递归比较两个 cJSON 对象，相同返回1，不同返回0
int cJSON_Compare(const cJSON * const a, const cJSON * const b, int case_sensitive) {
    // 1. 处理空指针情况
    if (a == b) return 1; // 相同对象
    if (a == NULL || b == NULL) return 0; // 任一为空
    
    // 2. 检查类型是否相同
    if (a->type != b->type) return 0;
    
    // 3. 根据类型进行比较
    switch (a->type) {
        case cJSON_NULL:
            return 1; // 两个都是NULL
            
        case cJSON_False:
        case cJSON_True:
            // 布尔值比较 valueint
            return (a->valueint == b->valueint);
            
        case cJSON_Number:
            // 数值比较，处理浮点精度问题
            return double_compare(a->valuedouble, b->valuedouble) == 0;
            
        case cJSON_String:
            // 字符串比较
            return string_compare(a->valuestring, b->valuestring, case_sensitive) == 0;
            
        case cJSON_Array: {
            // 数组比较
            cJSON *a_item = a->child;
            cJSON *b_item = b->child;
            int count = 0;
            
            // 比较数组长度
            while (a_item && b_item) {
                count++;
                a_item = a_item->next;
                b_item = b_item->next;
            }
            if (a_item || b_item) return 0; // 长度不相等
            
            // 递归比较每个元素
            a_item = a->child;
            b_item = b->child;
            while (a_item && b_item) {
                if (!cJSON_Compare(a_item, b_item, case_sensitive)) {
                    return 0;
                }
                a_item = a_item->next;
                b_item = b_item->next;
            }
            return 1;
        }
            
        case cJSON_Object: {
            // 对象比较
            cJSON *a_item = a->child;
            cJSON *b_item = b->child;
            int a_count = 0, b_count = 0;
            
            // 计算键值对数量
            while (a_item) {
                a_count++;
                a_item = a_item->next;
            }
            while (b_item) {
                b_count++;
                b_item = b_item->next;
            }
            if (a_count != b_count) return 0; // 键值对数量不相等
            
            // 遍历每个键值对
            a_item = a->child;
            while (a_item) {
                const char *key = a_item->string;
                b_item = b->child;
                int found = 0;
                
                while (b_item) {
                    // 键名比较（区分大小写）
                    if (key && b_item->string && 
                        string_compare(key, b_item->string, 1) == 0) {
                        found = 1;
                        // 递归比较值
                        if (!cJSON_Compare(a_item, b_item, case_sensitive)) {
                            return 0;
                        }
                        break;
                    }
                    b_item = b_item->next;
                }
                
                if (!found) return 0; // 键不存在
                a_item = a_item->next;
            }
            return 1;
        }
            
        default:
            // 未知类型
            return 0;
    }
}

